import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));

/**
 * 1：jsx
 * 2：组件
 * 3：State
 * 4：Props
 

var myStyle = { color: 'red', textAlign: 'center' }
class Name extends React.Component {
  render() {
    return <h1 style={myStyle}>网站名称：{this.props.name}</h1>;
  }
}
class Url extends React.Component {
  render() {
    return <h1>网站地址：{this.props.url}</h1>;
  }
}
// es6定义组件
class Nickname extends React.Component {
  render() {
    return <h1>网站地址：{this.props.nickname}</h1>;
  }
}
// 原生方法定义组件
function HlloWord(props) {
  return <h1>组件{props.name}</h1>
}

// state状态

// componentDidMount() 与 componentWillUnmount() 方法被称作生命周期钩子。
// 在组件输出到 DOM 后会执行 componentDidMount() 钩子，我们就可以在这个钩子上设置一个定时器。
// this.timDer 为定时器的 ID，我们可以在 componentWillUnmount() 钩子中卸载定时器。

// 另外一种
// 数据自顶向下流动
function FormText(props) {
  console.log(props, '传递的参数')
  return (
    <div>
      <h1>Hello, world state状态!</h1>
      <h2>现在是 {props.date.toLocaleTimeString()}</h2>
    </div>
  );
}
class Clock extends React.Component {
  constructor(props) {
    super(props)
    this.state = { date: new Date() };
  }
  componentDidMount() {
    // 设置定时器 让浏览器每一秒执行一次tick()方法
    // this.timDer = setInterval(() => this.tick(), 1000)
  }
  componentWillUnmount() {
    // 卸载定时器
    clearInterval(this.timDer)
  }

  tick() {
    // 去修改state中的时间
    this.setState({
      date: new Date()
    })
  }

  // 固定写法
  // render() {
  //   return (
  //     <div>
  //       <h1>Hello, world state状态!</h1>
  //       <h2>现在是 {this.state.date.toLocaleTimeString()}</h2>
  //     </div>
  //   );
  // }


  // 为了表明所有组件都是真正隔离的，我们可以创建一个 App 组件，它渲染三个Clock
  render() {
    return (
      <div>
        <FormText date={this.state.date} />
      </div>
    )
  }
}

// React Props
// state 和 props 主要的区别在于 props 是不可变的，
// 而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 
// 来更新和修改数据。 而子组件只能通过 props 来传递数据。
function Podes(props){
  return <h1>Hello {props.name}!</h1>;
}

// 你可以通过组件类的 defaultProps 属性为 props 设置默认值，实例如下： 
class Pros extends React.Component {
  render(){
    return (<h1>Hello {this.props.name}!</h1>);
  }

}

Pros.defaultProps = {
    name:"Props"
}


// 以下实例演示了如何在应用中组合使用 state 和 props 。我们可以在父组件中设置 state， 
// 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据。
class Namec extends React.Component {
  render() {
    return (
      <h1>{this.props.name}</h1>
    );
  }
}
 
class Site extends React.Component {
  render() {
    return (
      <a href={this.props.site}>
        {this.props.site}
      </a>
    );
  }
}


class WebSite extends React.Component{
  constructor(){
    super();
    this.state = {
      name:"学习react",
      site:"www.baidu.com"
    }

  }
  render(){
    return (
      <div>
        <Namec name={this.state.name} />
        <Site site={this.state.site} />
      </div>
    )
  }
}



// 父子通讯

export default class CptBody extends React.Component{
  // es6 类构造器
  constructor(){
      super();
      this.state = {username : "父级名称"}; //可以传json等很多格式（这个是初始化赋值）
  }
  //click事件函数
  changeAge(){
      // this.setState({username:"父级名称--修改"})
      // 互相传值
      this.setState({
      state:this.state.username++
      })
  }
  //change事件函数
  changeUsername(event){
      this.setState({username:event.target.value})
  }
  render(){
     return(
          <div>
              <h1>这里是主体内容部分</h1>
              <p>{this.state.username}</p>
              <input type="button" value="点击改变username" onClick={this.changeAge.bind(this)}/>
              <BodyChild changeUsername={this.changeUsername.bind(this)}/>
          </div>
      )
  }
}

// 子组件
class BodyChild extends React.Component{
  render(){
      return(
          <div>
              <p>子页面输出：<input type='text' onChange={this.props.changeUsername} /></p>
          </div>
      )
  }
}


function App(props) {
  return (
    <div>
      <HlloWord name="我是组件嘛" />,
      <Clock />,
      <Clock />,
      <Clock />,
      <h1>Hello, world!</h1>,
      <p data-myattribute="somevalue">这是一个很不错的 JavaScript 库!</p>
      <Name name={props.name} />
      <Url url={props.url} />
      <Nickname nickname={props.nickname} />

      <h1>Props</h1>
      <Podes name="Props"/>;
      <Pros />
      <WebSite data-name="区别" />
      <CptBody />
    </div>
  );
}



// 
root.render(
  <div>
    <HlloWord name="我是组件嘛" />,
    <App name={"yyds"} url={"http://www.runoob.com"} nickname={"Runoob"} />,
  </div>
);

* 
*/


/**
 * 
 * @param {*} props 
 * @returns 
 * 事件处理
 */

//  在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为， 你必须明确使用 preventDefault。
//  例如，通常我们在 HTML 中阻止链接默认打开一个新页面，可以这样写： 

function ActionLink() {
  // 点击事件
  function handleClick(e) {
    // 阻止默认事件 ---> 跳转
    e.preventDefault();
    console.log('链接被点击');
  }

  return (
    <a href="#" onClick={handleClick}>
      点我
    </a>
  );
}



// 使用 React 的时候通常你不需要使用 addEventListener 为一个已创建的 DOM 元素添加监听器。你仅仅需要在这个元素初始渲染的时候提供一个监听器。
// 当你使用 ES6 class 语法来定义一个组件的时候，事件处理器会成为类的一个方法。例如，下面的 Toggle 组件渲染一个让用户切换开关状态的按钮：

class Toggles extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isToggles: true
    };
    // 绑定 this 才能在回调函数中使用
    this.handleClick = this.handleClick.bind(this)
  }



  handleClick() {
    // this.setState(r =>{
    //   console.log(r) //参数
    // })
    this.setState(prevState => ({
      isToggles: !prevState.isToggles
    }));
  }
  // 如果你没有使用属性初始化器语法，你可以在回调函数中使用 箭头函数：
  handleClicks() {
    console.log(this, 'this')
    this.setState(prevState => ({
      isToggles: !prevState.isToggles
    }));
  }


  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          {this.state.isToggles ? 'ON' : 'OFF'}
        </button>
        <button onClick={(e) => this.handleClicks(e)}>
          {this.state.isToggles ? 'ON' : 'OFF'}
        </button>
      </div>


    );
  }
}


// 运算符
// 普通函数之间的
function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  let ssd = handleLoginClick.bind(props);
  function handleLoginClick(e){
    console.log(e)
  }

  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting onClicks={ssd} />;
}

function UserGreeting(props) {
  return <div>
    <h1>欢迎回来!</h1>
  </div>;
}

function GuestGreeting(props) {
  return <div>
  <h1>1111!</h1>
  {/* 并且使用箭头函数是向回调函数传递参数的最简单的办法 */}
  <button onClick={() => props.onClicks ('zach')}>Click Me</button>
</div>;
}




function App(props) {
  return (
    <div>
      <ActionLink />
      <br />
      <br />
      <br />
      <br />
      <Toggles />
    </div>
  )
}

root.render(
  <div>
    <App />
    <Greeting  isLoggedIn={false} />
  </div>
)

reportWebVitals();
